package com.zenithmind.coding.pojo.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.*;
import lombok.Data;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 竞赛创建DTO
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Data
@Schema(description = "竞赛创建DTO")
public class ContestCreateDTO {

    /**
     * 竞赛标题
     */
    @NotBlank(message = "竞赛标题不能为空")
    @Size(max = 200, message = "竞赛标题长度不能超过200个字符")
    @Schema(description = "竞赛标题", example = "2025年春季编程竞赛")
    private String title;

    /**
     * 竞赛描述
     */
    @Size(max = 5000, message = "竞赛描述长度不能超过5000个字符")
    @Schema(description = "竞赛描述")
    private String description;

    /**
     * 竞赛规则
     */
    @Size(max = 10000, message = "竞赛规则长度不能超过10000个字符")
    @Schema(description = "竞赛规则")
    private String rules;

    /**
     * 竞赛类型（1-个人赛，2-团队赛，3-练习赛，4-正式赛）
     */
    @NotNull(message = "竞赛类型不能为空")
    @Min(value = 1, message = "竞赛类型值无效")
    @Max(value = 4, message = "竞赛类型值无效")
    @Schema(description = "竞赛类型（1-个人赛，2-团队赛，3-练习赛，4-正式赛）", example = "1")
    private Integer type;

    /**
     * 竞赛模式（1-ACM模式，2-OI模式，3-IOI模式）
     */
    @NotNull(message = "竞赛模式不能为空")
    @Min(value = 1, message = "竞赛模式值无效")
    @Max(value = 3, message = "竞赛模式值无效")
    @Schema(description = "竞赛模式（1-ACM模式，2-OI模式，3-IOI模式）", example = "1")
    private Integer mode;

    /**
     * 开始时间
     */
    @NotNull(message = "开始时间不能为空")
    @Future(message = "开始时间必须是未来时间")
    @Schema(description = "开始时间")
    private LocalDateTime startTime;

    /**
     * 结束时间
     */
    @NotNull(message = "结束时间不能为空")
    @Future(message = "结束时间必须是未来时间")
    @Schema(description = "结束时间")
    private LocalDateTime endTime;

    /**
     * 持续时间（分钟）
     */
    @NotNull(message = "持续时间不能为空")
    @Min(value = 30, message = "持续时间不能少于30分钟")
    @Max(value = 10080, message = "持续时间不能超过7天")
    @Schema(description = "持续时间（分钟）", example = "180")
    private Integer duration;

    /**
     * 最大参与人数
     */
    @Min(value = 1, message = "最大参与人数不能少于1")
    @Max(value = 10000, message = "最大参与人数不能超过10000")
    @Schema(description = "最大参与人数", example = "100")
    private Integer maxParticipants;

    /**
     * 是否公开（0-私有，1-公开）
     */
    @NotNull(message = "是否公开不能为空")
    @Min(value = 0, message = "是否公开值无效")
    @Max(value = 1, message = "是否公开值无效")
    @Schema(description = "是否公开（0-私有，1-公开）", example = "1")
    private Integer isPublic;

    /**
     * 是否需要密码（0-否，1-是）
     */
    @NotNull(message = "是否需要密码不能为空")
    @Min(value = 0, message = "是否需要密码值无效")
    @Max(value = 1, message = "是否需要密码值无效")
    @Schema(description = "是否需要密码（0-否，1-是）", example = "0")
    private Integer needPassword;

    /**
     * 竞赛密码
     */
    @Size(max = 50, message = "竞赛密码长度不能超过50个字符")
    @Schema(description = "竞赛密码")
    private String password;

    /**
     * 奖励设置（JSON格式）
     */
    @Size(max = 2000, message = "奖励设置长度不能超过2000个字符")
    @Schema(description = "奖励设置（JSON格式）")
    private String rewards;

    /**
     * 竞赛标签（JSON格式）
     */
    @Size(max = 500, message = "竞赛标签长度不能超过500个字符")
    @Schema(description = "竞赛标签（JSON格式）")
    private String tags;

    /**
     * 竞赛封面图片URL
     */
    @Size(max = 500, message = "封面图片URL长度不能超过500个字符")
    @Schema(description = "竞赛封面图片URL")
    private String coverImage;

    /**
     * 竞赛问题ID列表
     */
    @NotEmpty(message = "竞赛问题列表不能为空")
    @Size(min = 1, max = 20, message = "竞赛问题数量必须在1-20之间")
    @Schema(description = "竞赛问题ID列表")
    private List<String> problemIds;

    /**
     * 是否允许查看他人代码（0-否，1-是）
     */
    @NotNull(message = "是否允许查看他人代码不能为空")
    @Min(value = 0, message = "是否允许查看他人代码值无效")
    @Max(value = 1, message = "是否允许查看他人代码值无效")
    @Schema(description = "是否允许查看他人代码（0-否，1-是）", example = "0")
    private Integer allowViewOthersCode;

    /**
     * 是否允许讨论（0-否，1-是）
     */
    @NotNull(message = "是否允许讨论不能为空")
    @Min(value = 0, message = "是否允许讨论值无效")
    @Max(value = 1, message = "是否允许讨论值无效")
    @Schema(description = "是否允许讨论（0-否，1-是）", example = "1")
    private Integer allowDiscussion;

    /**
     * 是否实时排行榜（0-否，1-是）
     */
    @NotNull(message = "是否实时排行榜不能为空")
    @Min(value = 0, message = "是否实时排行榜值无效")
    @Max(value = 1, message = "是否实时排行榜值无效")
    @Schema(description = "是否实时排行榜（0-否，1-是）", example = "1")
    private Integer realtimeRanking;

    /**
     * 排序值
     */
    @Min(value = 0, message = "排序值不能为负数")
    @Schema(description = "排序值", example = "0")
    private Integer sortOrder;

    /**
     * 验证结束时间是否在开始时间之后
     */
    @AssertTrue(message = "结束时间必须在开始时间之后")
    private boolean isEndTimeAfterStartTime() {
        if (startTime == null || endTime == null) {
            return true; // 让其他验证处理null值
        }
        return endTime.isAfter(startTime);
    }

    /**
     * 验证持续时间是否与开始结束时间匹配
     */
    @AssertTrue(message = "持续时间与开始结束时间不匹配")
    private boolean isDurationMatched() {
        if (startTime == null || endTime == null || duration == null) {
            return true; // 让其他验证处理null值
        }
        long actualDuration = java.time.Duration.between(startTime, endTime).toMinutes();
        return Math.abs(actualDuration - duration) <= 1; // 允许1分钟的误差
    }

    /**
     * 验证密码设置
     */
    @AssertTrue(message = "需要密码时必须设置密码")
    private boolean isPasswordValid() {
        if (needPassword == null) {
            return true;
        }
        if (needPassword == 1) {
            return password != null && !password.trim().isEmpty();
        }
        return true;
    }
}
